23. quickReject

quickReject()

The quickReject() method allows you to check whether a specified rectangle or path would lie completely outside the currently visible regions, after all transformations have been applied.

The quickReject() method is incredibly useful when you are constructing more complex drawings and need to do so as fast as possible. With quickReject(), you can decide efficiently which objects you do not have to draw at all, and there is no need to write your own intersection logic.

  • The quickReject() method returns true if the rectangle or path would not be visible at all on the screen. For partial overlaps, you still have to do your own checking.

  • The EdgeType is either AA (Antialiased: Treat edges by rounding-out, because they may be antialiased) or BW (Black-White: Treat edges by just rounding to nearest pixel boundary) for just rounding to the nearest pixel.

There are several versions of quickReject(), and you can also find them in the documentation.

In this exercise, you are going to draw in a new row, below the text, and inside the clipRect, as before.

  • You first call quickReject() with a rectangle inClipRectangle, that overlaps with clipRect. So quickReject() returns false, clipRect is filled with BLACK, and the inClipRectangle rectangle is drawn.

  • Then change the code and call quickReject(), with notInClipRectangle. quickReject() now returns true, and clipRect is filled with WHITE, and notInClipRectangle is not drawn.

When you have complex drawings, this can quickly tell you, which shapes are completely outside the clipping region, and for which you may have to do additional calculations, and drawing, because they are partially or fully inside the clipping region.

Exercise

  1. At the top-level, create a variable for the y coordinates of an additional row.
private val rejectRow = rowFour + rectInset + 2*clipRectBottom
  1. Add the following drawQuickRejectExample() function to ClippedView, and uncomment its invocation in onDraw(). Read the code, as it contains everything you need to know to use quickReject().
private fun drawQuickRejectExample(canvas: Canvas) {
   val inClipRectangle = RectF(clipRectRight / 2,
       clipRectBottom / 2,
       clipRectRight * 2,
       clipRectBottom * 2)

   val notInClipRectangle = RectF(RectF(clipRectRight+1,
       clipRectBottom+1,
       clipRectRight * 2,
       clipRectBottom * 2))

   canvas.save()
   canvas.translate(columnOne, rejectRow)
   canvas.clipRect(
       clipRectLeft,clipRectTop,
       clipRectRight,clipRectBottom
   )
   if (canvas.quickReject(
           inClipRectangle, Canvas.EdgeType.AA)) {
       canvas.drawColor(Color.WHITE)
   }
   else {
       canvas.drawColor(Color.BLACK)
       canvas.drawRect(inClipRectangle, paint
       )
   }
       canvas.restore()
}
  1. Run your app, and you will see a black rectangle, which is the filled clipping region, and parts of the inClipRectangle, because the two rectangles overlap, so quickReject() returns false and inClipRectangle is drawn.

  1. Change the code to run quickReject() against notInClipRectangle. Now quickReject() returns true and the clipping region is filled with white.